package com.nowcoder.topic.bisection.middle;

import java.util.TreeSet;

/**
 * NC79 丑数
 * @author d3y1
 */
public class NC79{
    /**
     * 代码中的类名、方法名、参数名已经指定，请勿修改，直接返回方法规定的值即可
     *
     *
     * @param index int整型
     * @return int整型
     */
    public int GetUglyNumber_Solution (int index) {
//        return solution1(index);
//        return solution2(index);
        return solution3(index);
    }

    /**
     * 循环判断: 超时!
     * @param index
     * @return
     */
    private int solution1(int index){
        if(index == 0){
            return 0;
        }

        int count = 0;
        int num = 1;
        while(true){
            if(isUglyNum(num)){
                count++;
            }
            if(count == index){
                return num;
            }
            num++;
        }
    }

    /**
     * 是否丑数
     * @param num
     * @return
     */
    private boolean isUglyNum(int num){
        while(num%2 == 0){
            num /= 2;
        }
        while(num%3 == 0){
            num /= 3;
        }
        while(num%5 == 0){
            num /= 5;
        }

        return num==1;
    }

    /**
     * 生成丑数: TreeSet
     * @param index
     * @return
     */
    private int solution2(int index){
        if(index == 0){
            return 0;
        }

        TreeSet<Long> treeSet = new TreeSet<>();
        treeSet.add(1L);

        long[] ugly = new long[index];

        long min;
        for(int curr=0; curr<index; curr++){
            // 下一个最小丑数
            min = treeSet.pollFirst();
            ugly[curr] = min;
            // 生成丑数
            treeSet.add(min*2);
            treeSet.add(min*3);
            treeSet.add(min*5);
        }

        return (int)ugly[index-1];
    }

    /**
     * 生成丑数: 三指针
     * @param index
     * @return
     */
    private int solution3(int index){
        if(index == 0){
            return 0;
        }

        int[] ugly = new int[index];
        ugly[0] = 1;

        // 三指针
        int i=0,j=0,k=0;
        int min;
        for(int curr=1; curr<index; curr++){
            // 下一个最小丑数
            min = Math.min(ugly[i]*2, Math.min(ugly[j]*3, ugly[k]*5));
            ugly[curr] = min;
            // 指针移位 -> 生成下一个最小丑数
            if(min == ugly[i]*2){
                i++;
            }
            if(min == ugly[j]*3){
                j++;
            }
            if(min == ugly[k]*5){
                k++;
            }
        }

        return ugly[index-1];
    }
}